package com.aiti.lulian.workflow;


import com.aiti.lulian.mapper.ProcessInstanceMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
public class ProcessInstanceManager {

    @Autowired
    private ProcessInstanceMapper processInstanceMapper;

    @Autowired
    private ProcessDefinitionManager processDefinitionManager;

    public ProcessInstance save(ProcessInstance processInstance) {
        processInstanceMapper.insert(processInstance);
        return processInstance;
    }

    public ProcessInstance update(ProcessInstance processInstance) {
        processInstanceMapper.updateById(processInstance);
        return processInstance;
    }

    public ProcessInstance findById(String id) {
        ProcessInstance processInstance = processInstanceMapper.selectById(id);
        if (processInstance != null) {
            ProcessDefinition definition = processDefinitionManager.findById(processInstance.getProcessDefinitionId());
            if(definition != null){
                processInstance.setProcessDefinition(definition);
            }

        }

        return processInstance;
    }

    public List<ProcessInstance> findByProcessDefinitionId(String processDefinitionId) {
        return processInstanceMapper.findByProcessDefinitionId(processDefinitionId);
    }

    public List<ProcessInstance> findByBusinessKey(String businessKey) {
        return processInstanceMapper.findByBusinessKey(businessKey);
    }

    public List<ProcessInstance> findByStatus(ProcessStatus status) {
        return processInstanceMapper.findByStatus(status);
    }

    @Transactional
    public ProcessInstance createInstance(String processDefinitionId, String businessKey,
                                          String starterUserId, Object formData) {
        ProcessDefinition definition = processDefinitionManager.findActiveById(processDefinitionId);
        if (definition == null) {
            throw new RuntimeException("流程定义未找到或未激活: " + processDefinitionId);
        }

        ProcessInstance instance = new ProcessInstance();
        instance.setId("instance_" + System.currentTimeMillis());
        instance.setProcessDefinitionId(processDefinitionId);
        instance.setProcessDefinition(definition);
        instance.setBusinessKey(businessKey);
        instance.setStatus(ProcessStatus.SUBMITTED);


        if (formData != null) {
            instance.setVariables(formDataToMap(formData));
        }


        instance.setCurrentNodeId(definition.getStartNode().getId());
        processInstanceMapper.insert(instance);
        return instance;
    }

    @Transactional
    public void terminateInstance(String instanceId, String reason) {
        ProcessInstance processInstance = findById(instanceId);
        if (processInstance != null) {

            processInstance.terminate();
            processInstanceMapper.insert(processInstance);

            // 记录终止原因到变量或历史
            processInstance.setVariable("terminationReason", reason);
            processInstanceMapper.insert(processInstance);
        }
    }

    @Transactional
    public void suspendInstance(String instanceId) {
        ProcessInstance processInstance = findById(instanceId);
        if (processInstance != null) {
            processInstance.suspend();
            processInstanceMapper.insert(processInstance);
        }
    }

    @Transactional
    public void resumeInstance(String instanceId) {
        ProcessInstance processInstance = findById(instanceId);
        if (processInstance != null) {
            processInstance.resume();
            processInstanceMapper.insert(processInstance);
        }
    }

    public Map<String, Object> formDataToMap(Object formData) {
        if (formData == null) {
            return new HashMap<>();
        }


        if (formData instanceof Map) {

            return new HashMap<>((Map<String, Object>) formData);
        }


        if (formData instanceof String) {
            try {
                ObjectMapper mapper = new ObjectMapper();
                return mapper.readValue((String) formData, Map.class);
            } catch (Exception e) {
                throw new IllegalArgumentException("错误的json", e);
            }
        }


        try {
            ObjectMapper mapper = new ObjectMapper();
            return mapper.convertValue(formData, Map.class);
        } catch (Exception e) {
            throw new IllegalArgumentException("转换map错误", e);
        }
    }

}